package com.real8.romemp.client.activity;

import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.real8.romemp.client.ClientFactory;
import com.real8.romemp.client.GameConstants;
import com.real8.romemp.client.GameMessages;
import com.real8.romemp.client.place.PiracyPlace;
import com.real8.romemp.client.place.WarPlace;
import com.real8.romemp.client.ui.WarView;
import com.real8.romemp.client.ui.WarView.Presenter;
import com.real8.romemp.shared.GameData;

public class WarActivity extends AbstractActivity implements Presenter {
	private enum EWarStep {
		WAR_TYPE, WAR_LOSSES, TRADE_RATE
	}

	private final ClientFactory clientFactory;
	private WarView view;

	private EWarStep warStep;

	private int PP_warTypeNumber;

	private int G_tradeRateChange;
	private double H; // TODO: what is this?
	private int ZB_warChance;
	private int ZC_winChance;
	private int PX_remainingPopulationPercent;
	private int FX_remainingFoodReservePercent;

	public WarActivity(WarPlace place, ClientFactory clientFactory) {
		this.clientFactory = clientFactory;
	}

	@Override
	public void start(AcceptsOneWidget containerWidget, EventBus eventBus) {
		view = clientFactory.getWarView();
		if (view != null) {
			view.setPresenter(this);

			// prepare view
			view.hideAll();

			// show war warning
			view.showWarWarning();

			// delay a bit
			Timer timer = new Timer() {
				@Override
				public void run() {
					warStep = EWarStep.WAR_TYPE;
					GameData gameData = clientFactory.getGameData();
					PP_warTypeNumber = Random.nextInt(1000) + 1
							+ gameData.getVF_popularity() * 3;
					if (PP_warTypeNumber > 950) {
						//
						gameData
								.setVF_popularity(gameData.getVF_popularity() + 5);
						G_tradeRateChange = Random.nextInt(3) + 1;
						PX_remainingPopulationPercent = 100;
						FX_remainingFoodReservePercent = 100;
						// TODO init ZB & ZC?

						// show no war
						view.showNoWar();
					} else {
						// determine what kind of war / revolt
						GameMessages messages = (GameMessages) GWT
								.create(GameMessages.class);
						String A = "";
						String B = "";
						if (PP_warTypeNumber < 175) {
							A = messages.war();
							B = messages.withCarthago();
							G_tradeRateChange = Random.nextInt(15) + 5;
							H = 1.8;
						} else if (PP_warTypeNumber < 350) {
							A = messages.revolt();
							B = messages.inGallie();
							G_tradeRateChange = Random.nextInt(12) + 3;
							H = 1.6;
						} else if (PP_warTypeNumber < 450) {
							A = messages.revolt();
							B = messages.inBritain();
							G_tradeRateChange = Random.nextInt(12) + 3;
							H = 1.6;
						} else if (PP_warTypeNumber < 525) {
							A = messages.war();
							B = messages.withMacedonia();
							G_tradeRateChange = Random.nextInt(10) + 2;
							H = 1.4;
						} else if (PP_warTypeNumber < 625) {
							A = messages.war();
							B = messages.withTheParthians();
							G_tradeRateChange = Random.nextInt(10) + 2;
							H = 1.4;
						} else if (PP_warTypeNumber < 675) {
							A = messages.war();
							B = messages.withTheGreeks();
							G_tradeRateChange = Random.nextInt(8) + 1;
							H = 1.2;
						} else if (PP_warTypeNumber < 750) {
							A = messages.war();
							B = messages.withThePicts();
							G_tradeRateChange = Random.nextInt(8) + 1;
							H = 1.2;
						} else if (PP_warTypeNumber < 875) {
							A = messages.revolt();
							B = messages.inJudea();
							G_tradeRateChange = Random.nextInt(8) + 1;
							H = 1.2;
						} else if (PP_warTypeNumber < 925) {
							A = messages.revolt();
							B = messages.inSpain();
							G_tradeRateChange = Random.nextInt(4) + 1;
							H = 1.0;
						} else {
							A = messages.revolt();
							B = messages.onCrete();
							G_tradeRateChange = Random.nextInt(4) + 3;
							H = 1.0;
						}

						// show war
						view.showWar(messages.brokeOut(A, B));
					}

					// delay a bit
					Timer timer = new Timer() {
						@Override
						public void run() {
							// show continue
							view.showContinue();
						}
					};
					timer.schedule(GameConstants.DELAY_6020);
				}
			};
			timer.schedule(GameConstants.DELAY_6010);

			// set widget
			containerWidget.setWidget(view.asWidget());
		}
	}

	@Override
	public void onContinue() {
		switch (warStep) {
		case WAR_TYPE:
			goToLosses();
			break;
		case WAR_LOSSES:
			goToTradeRate();
			break;
		case TRADE_RATE:
			goToNextPlace();
			break;
		}
	}

	private void goToLosses() {
		warStep = EWarStep.WAR_LOSSES;

		// check war / revolt
		if (PP_warTypeNumber > 950) {
			goToTradeRate();
		} else {
			// ..
			ZB_warChance = Random.nextInt(100) + 1;

			// calculate win chance
			final GameData gameData = clientFactory.getGameData();
			int TN = gameData.getTN_year();
			double ZD = 0;
			if (TN < -50) {
				ZD = 2;
			} else if (TN < -45) {
				ZD = 1.5;
			} else if (TN < -40) {
				ZD = 1;
			} else if (TN < -35) {
				ZD = 0.75;
			}
			ZC_winChance = (int) ((gameData.getLA_labourArmy()
					+ gameData.getMH_auxiliaHired() + (gameData
					.getWL_localWarShips() / 3))
					* ZD / H);
			if (ZC_winChance > 100) {
				ZC_winChance = 99;
			}

			// show win chance
			view.hideAll();
			view.showWinChance(ZC_winChance);

			// delay
			Timer timer = new Timer() {
				private int WW_lostLocalWarShips;
				private int MW_lostLocalMerchantShips;
				private int MX_lostOverseeMerchantShips;
				private int WX_lostOverseeWarShips;
				private int AW_lostArmy;
				private int SW_lostAuxilia;
				private int SX_lostShipBuilders;
				private int EX_lostArtisans;

				@Override
				public void run() {
					// check win / lose
					if (ZB_warChance > ZC_winChance) {
						// defeated

						// calculate losses
						WW_lostLocalWarShips = (int) (Random.nextInt(10) + 1 * H);
						if (WW_lostLocalWarShips > gameData
								.getWL_localWarShips()) {
							WW_lostLocalWarShips = gameData
									.getWL_localWarShips();
						}
						MW_lostLocalMerchantShips = (int) (Random.nextInt(20) + 7 * H);
						if (MW_lostLocalMerchantShips > gameData
								.getML_localMerchantShips()) {
							MW_lostLocalMerchantShips = gameData
									.getML_localMerchantShips();
						}
						MX_lostOverseeMerchantShips = (int) (Random.nextInt(5) + 2 * H);
						if (MX_lostOverseeMerchantShips > gameData
								.getMO_overseeMerchantShips()) {
							MX_lostOverseeMerchantShips = gameData
									.getMO_overseeMerchantShips();
						}
						WX_lostOverseeWarShips = (int) (Random.nextInt(3) + 1 * H);
						if (WX_lostOverseeWarShips > gameData
								.getWO_overseeWarShips()) {
							WX_lostOverseeWarShips = gameData
									.getWO_overseeWarShips();
						}
						AW_lostArmy = (int) (Random.nextInt(6) + 1 * H);
						if (AW_lostArmy > gameData.getLA_labourArmy()) {
							AW_lostArmy = gameData.getLA_labourArmy();
						}
						SW_lostAuxilia = (int) (Random.nextInt(8) + 1 * H);
						if (SW_lostAuxilia > gameData.getMH_auxiliaHired()) {
							SW_lostAuxilia = gameData.getMH_auxiliaHired();
						}
						FX_remainingFoodReservePercent = Random.nextInt(20) + 79;
						PX_remainingPopulationPercent = Random.nextInt(5) + 95;
						SX_lostShipBuilders = (int) (Random.nextInt(3) * H);
						if (SX_lostShipBuilders > gameData
								.getLS_labourShipBuilders()) {
							SX_lostShipBuilders = gameData
									.getLS_labourShipBuilders();
						}
						EX_lostArtisans = (int) (Random.nextInt(3) * H);
						if (EX_lostArtisans > gameData.getLE_labourArtisans()) {
							EX_lostArtisans = gameData.getLE_labourArtisans();
						}
						gameData.setVF_popularity(gameData.getVF_popularity()
								- G_tradeRateChange * 2);

						// show defeated
						view.showDefeated();

					} else {
						// victorious

						// calculate losses
						WW_lostLocalWarShips = (int) (Random.nextInt(5) + 1 * H);
						if (WW_lostLocalWarShips > gameData
								.getWL_localWarShips()) {
							WW_lostLocalWarShips = gameData
									.getWL_localWarShips();
						}
						MW_lostLocalMerchantShips = (int) (Random.nextInt(10) + 3 * H);
						if (MW_lostLocalMerchantShips > gameData
								.getML_localMerchantShips()) {
							MW_lostLocalMerchantShips = gameData
									.getML_localMerchantShips();
						}
						MX_lostOverseeMerchantShips = 1;
						if (MX_lostOverseeMerchantShips > gameData
								.getMO_overseeMerchantShips()) {
							MX_lostOverseeMerchantShips = 0;
						}
						WX_lostOverseeWarShips = 0;
						AW_lostArmy = (int) (Random.nextInt(2) + 1 * H);
						if (AW_lostArmy > gameData.getLA_labourArmy()) {
							AW_lostArmy = gameData.getLA_labourArmy();
						}
						SW_lostAuxilia = (int) (Random.nextInt(3) + 1 * H);
						if (SW_lostAuxilia > gameData.getMH_auxiliaHired()) {
							SW_lostAuxilia = gameData.getMH_auxiliaHired();
						}
						FX_remainingFoodReservePercent = 100;
						PX_remainingPopulationPercent = 100;
						SX_lostShipBuilders = 0;
						EX_lostArtisans = 0;
						gameData.setVF_popularity(gameData.getVF_popularity()
								+ (int) (G_tradeRateChange * 1.5));

						// show victorious
						view.showVictorious();
					}

					// set losses
					gameData.setWS_warShips(gameData.getWS_warShips()
							- WW_lostLocalWarShips - WX_lostOverseeWarShips);
					gameData.setLN_labourNavy(gameData.getLN_labourNavy()
							- WW_lostLocalWarShips - WX_lostOverseeWarShips);
					gameData.setMS_merchantShips(gameData.getMS_merchantShips()
							- MW_lostLocalMerchantShips
							- MX_lostOverseeMerchantShips);
					gameData.setLM_labourMerchants(gameData
							.getLM_labourMerchants()
							- MW_lostLocalMerchantShips
							- MX_lostOverseeMerchantShips);
					gameData.setLA_labourArmy(gameData.getLA_labourArmy()
							- AW_lostArmy);
					gameData.setMH_auxiliaHired(gameData.getMH_auxiliaHired()
							- SW_lostAuxilia);
					gameData.setFS_foodReserve((gameData.getFS_foodReserve()
							* FX_remainingFoodReservePercent / 100));
					gameData.setPO_population(gameData.getPO_population()
							* PX_remainingPopulationPercent / 100);
					gameData.setLS_labourShipBuilders(gameData
							.getLS_labourShipBuilders()
							- SX_lostShipBuilders);
					gameData.setLE_labourArtisans(gameData
							.getLE_labourArtisans()
							- EX_lostArtisans);

					// show losses
					view.showLosses(WW_lostLocalWarShips,
							WX_lostOverseeWarShips, MW_lostLocalMerchantShips,
							MX_lostOverseeMerchantShips, AW_lostArmy,
							SW_lostAuxilia, FX_remainingFoodReservePercent,
							PX_remainingPopulationPercent, SX_lostShipBuilders,
							EX_lostArtisans);

					// show continue
					view.showContinue();
				}
			};
			timer.schedule(GameConstants.DELAY_6010);
		}
	}

	private void goToTradeRate() {
		warStep = EWarStep.TRADE_RATE;

		// show trade rate change
		GameData gameData = clientFactory.getGameData();
		view.hideAll();
		if (ZB_warChance <= ZC_winChance) {
			view.showTradeRateIncreased(G_tradeRateChange);

			gameData.setVL_tradeRate(gameData.getVL_tradeRate()
					+ G_tradeRateChange);
		} else {
			view.showTradeRateDecreased(G_tradeRateChange);

			gameData.setVL_tradeRate(gameData.getVL_tradeRate()
					- G_tradeRateChange);
		}

		// show trade rate
		view.showTradeRate(gameData.getVL_tradeRate());

		// show continue
		view.showContinue();
	}

	private void goToNextPlace() {
		clientFactory.getPlaceController().goTo(new PiracyPlace());
	}
}
